package me.henrydhc.naiveeconomy.account;

import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.logging.Logger;

import org.bukkit.Bukkit;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;

import me.henrydhc.naiveeconomy.cache.AccountCache;
import me.henrydhc.naiveeconomy.connector.Connector;
import me.henrydhc.naiveeconomy.task.CacheSaveTask;

public class AccountManager {

    private final Connector connector;
    private final AccountCache cache;
    private final Logger logger;

    public AccountManager(Connector connector, AccountCache cache, Logger logger) {
        this.connector = connector;
        this.cache = cache;
        this.logger = logger;
    }

    /**
     * Get econ account
     * @param playerID Player UUID
     * @return Player econ account
     */
    @Nullable
    public EcoAccount getAccount(@NonNull UUID playerID) {
        EcoAccount cacheAccount = cache.getAccount(playerID);

        if (cacheAccount != null) {
            return cacheAccount;
        }

        try {
            return connector.getAccount(playerID);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * Store account information
     * @param account Account data
     */
    public void saveAccount(@NonNull EcoAccount account) {

        if (cache.storeAccount(account)) {
            return;
        }

        EcoAccount oldesAccount = cache.removeOldestAccount();
        try {
            connector.saveAccount(oldesAccount);
        } catch (Exception e) {
            logger.severe("Failed to store cached account");
            logger.severe("Account ID: " + oldesAccount.getAccountUUID().toString());
            logger.severe("Player ID: " + oldesAccount.getOwnerUUID().toString());
            logger.severe("Balance: " + oldesAccount.getBalance());
            e.printStackTrace();
        }

        cache.storeAccount(account);

    }

    /**
     * Save all player accounts into database
     */
    public void saveAll() {
        
        if (isDisabling()) {
            new CacheSaveTask(connector, cache).run();
        } else {
            new CacheSaveTask(connector, cache).runTask(
                Bukkit.getPluginManager().getPlugin("NaiveEconomy")
            );
        }
        
    }

    private boolean isDisabling() {
        List<StackTraceElement> traces = Arrays.asList(Thread.currentThread().getStackTrace());
        boolean isOnDisable = traces.stream()
            .anyMatch(t -> t.getMethodName().equalsIgnoreCase("ondisable"));
        return isOnDisable;
    }
    
}
